Skip to content

refactor(transport): single-owner HTTP transport, fix util layering inversion#1213

Merged
liangshuo-1 merged 1 commit into
mainfrom
refactor/transport-single-owner
Jun 2, 2026
Merged

refactor(transport): single-owner HTTP transport, fix util layering inversion#1213
liangshuo-1 merged 1 commit into
mainfrom
refactor/transport-single-owner

Conversation

@liangshuo-1

@liangshuo-1 liangshuo-1 commented Jun 2, 2026

Copy link
Copy Markdown
Collaborator

Summary

Make internal/transport (renamed from internal/proxyplugin) the single owner of outbound HTTP transport, and remove the layering inversion that appeared when proxy-plugin mode was wired into internal/util.

Motivation

After #1181, internal/util imported internal/proxyplugin in four places (SharedTransport, FallbackTransport, NewHTTPClient, and WarnIfProxied via proxyPluginStatus). A foundational utility package — imported by ~18 packages — depended up into a feature package, pulling binding/core/vfs into the transitive cone of every util importer. The transport logic was also duplicated: two SharedTransport and two redactProxyURL implementations split across the two packages.

Changes

  • Rename internal/proxyplugininternal/transport; it now owns all transport assembly.
  • Fold the two SharedTransport into one transport.Shared() (precedence: proxy-plugin override → LARK_CLI_NO_PROXYhttp.DefaultTransport); demote the proxy-plugin probe to a private pluginTransport().
  • Move Fallback / NewHTTPClient / WarnIfProxied / DetectProxyEnv / noProxyTransport out of internal/util/proxy.go (deleted) into the new package; collapse the duplicate redactProxyURL to one.
  • internal/util keeps no proxy code, so it is a leaf again — the util → proxyplugin import edge is gone.
  • Re-point all consumers (registry, doctor, config, auth, cmdutil, update) to internal/transport.

Behavior-preserving: package move + symbol rename + de-duplication. No functional change to proxy-plugin mode, the NewHTTPClient egress chokepoint, the fail-closed transport, or the proxy/MITM warnings introduced in #1181.

Test Plan

  • go build ./...
  • go vet (affected packages)
  • gofmt -l clean
  • go test green: transport, util, cmdutil, auth, update, registry, doctor, config
  • New tests lock the fail-closed contract: proxy-plugin overrides LARK_CLI_NO_PROXY; a malformed proxy_config.json never falls through to direct egress.

Summary by CodeRabbit

  • Chores
    • Reorganized HTTP transport and proxy handling for consistent network behavior across the CLI.
    • Network checks and commands now follow the same proxy and egress rules, improving reliability of remote operations.
    • Improved proxy detection and one-time warning messages with redacted credentials and clearer TLS/CA warnings.
    • Added tests and safeguards to ensure no-proxy mode and malformed proxy configs behave predictably.

@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.


liangshuo-1 seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

@coderabbitai

coderabbitai Bot commented Jun 2, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 735eab86-f8a2-4055-8e9a-93451f5f48ca

📥 Commits

Reviewing files that changed from the base of the PR and between f6be704 and 6a540ba.

📒 Files selected for processing (19)
  • cmd/config/init_interactive.go
  • cmd/doctor/doctor.go
  • internal/auth/transport.go
  • internal/cmdutil/factory_default.go
  • internal/cmdutil/transport.go
  • internal/cmdutil/transport_test.go
  • internal/registry/remote.go
  • internal/transport/config.go
  • internal/transport/config_test.go
  • internal/transport/shared.go
  • internal/transport/shared_test.go
  • internal/transport/tls_ca.go
  • internal/transport/tls_ca_test.go
  • internal/transport/transport.go
  • internal/transport/transport_test.go
  • internal/transport/warn.go
  • internal/transport/warn_test.go
  • internal/update/update.go
  • internal/util/proxy.go
💤 Files with no reviewable changes (1)
  • internal/util/proxy.go
✅ Files skipped from review due to trivial changes (3)
  • internal/transport/tls_ca.go
  • internal/transport/tls_ca_test.go
  • internal/transport/config_test.go
🚧 Files skipped from review as they are similar to previous changes (15)
  • internal/cmdutil/transport_test.go
  • cmd/doctor/doctor.go
  • internal/auth/transport.go
  • internal/cmdutil/transport.go
  • cmd/config/init_interactive.go
  • internal/update/update.go
  • internal/transport/shared.go
  • internal/registry/remote.go
  • internal/transport/warn.go
  • internal/cmdutil/factory_default.go
  • internal/transport/transport.go
  • internal/transport/shared_test.go
  • internal/transport/transport_test.go
  • internal/transport/config.go
  • internal/transport/warn_test.go

📝 Walkthrough

Walkthrough

This PR consolidates HTTP transport and proxy-handling utilities by migrating proxy-aware transport, warning, and client helpers into a new internal/transport package and updating all call sites to use the new APIs.

Changes

HTTP Transport Consolidation

Layer / File(s) Summary
Package restructuring and relocation
internal/transport/config.go, internal/transport/transport.go, internal/transport/tls_ca.go, tests
Files previously in proxyplugin are converted to internal/transport; exported SharedTransport was internalized as pluginTransport and package declarations/comments updated.
Shared transport helpers and warnings
internal/transport/shared.go, internal/transport/warn.go
Added Shared(), Fallback(), NewHTTPClient(), no-proxy clone logic, DetectProxyEnv(), EnvNoProxy, and WarnIfProxied() with credential redaction and one-time semantics.
Shared transport test coverage
internal/transport/shared_test.go
New tests covering default behavior, no-proxy clone and caching, env toggles, system-proxy override, NewHTTPClient timeout, plugin override, and fail-closed behavior.
Plugin transport internalization
internal/transport/transport.go, internal/transport/transport_test.go
Exported SharedTransport() replaced by unexported pluginTransport(); tests updated to call internal function and assert fail-closed invariants.
Proxy warning test relocation
internal/transport/warn_test.go
Warn tests moved into transport package; helper code removed and tests reset plugin/warning state using resetProxyPluginState.
Command utility wrapper fallback updates
internal/cmdutil/transport.go, internal/cmdutil/transport_test.go
Round-tripper wrappers now use transport.Fallback() when Base is nil; test comment updated accordingly.
Factory and command infrastructure integration
internal/cmdutil/factory_default.go
Cached HTTP and Lark client construction call transport.WarnIfProxied() and seed RoundTrippers with transport.Shared(); buildSDKTransport() uses transport.Shared().
Auth transport fallback integration
internal/auth/transport.go
SecurityPolicyTransport.base() now uses transport.Fallback() when Base is nil.
Callsite migrations
cmd/config/init_interactive.go, cmd/doctor/doctor.go, internal/registry/remote.go, internal/update/update.go
Multiple command and service callsites switched from util.NewHTTPClient()/util.SharedTransport() to transport.NewHTTPClient()/transport.Shared().

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • larksuite/cli#247: Related refactor of shared fallback round-tripper usage and transport plumbing.
  • larksuite/cli#596: Overlaps with SDK transport chain updates in internal/cmdutil and round-tripper wrapper behavior.
  • larksuite/cli#1181: Prior work on proxy-plugin-aware transport behavior that this PR consolidates into a new package.

Suggested labels

size/L

Suggested reviewers

  • sang-neo03

Poem

🐰 Hopped through code to find a way,

Moved transports where they now should stay,
Proxies warned once, secrets masked tight,
Shared clients born to route requests right.
A little rabbit cheers the new networking light!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 72.09% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main refactoring: moving transport ownership to internal/transport and fixing the layering inversion between util and proxyplugin packages.
Description check ✅ Passed The PR description is comprehensive and follows the template structure with Summary, Motivation, Changes, and Test Plan sections all properly filled out with detailed information.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/transport-single-owner

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added the size/XL Architecture-level or global-impact change label Jun 2, 2026
@codecov

codecov Bot commented Jun 2, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 79.45205% with 15 lines in your changes missing coverage. Please review.
✅ Project coverage is 69.22%. Comparing base (bc8e9bd) to head (6a540ba).

Files with missing lines Patch % Lines
internal/transport/shared.go 71.42% 5 Missing and 1 partial ⚠️
internal/cmdutil/transport.go 25.00% 3 Missing ⚠️
cmd/config/init_interactive.go 0.00% 1 Missing ⚠️
cmd/doctor/doctor.go 0.00% 1 Missing ⚠️
internal/auth/transport.go 0.00% 1 Missing ⚠️
internal/cmdutil/factory_default.go 88.88% 1 Missing ⚠️
internal/transport/warn.go 96.96% 1 Missing ⚠️
internal/update/update.go 0.00% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1213   +/-   ##
=======================================
  Coverage   69.21%   69.22%           
=======================================
  Files         633      634    +1     
  Lines       59563    59555    -8     
=======================================
- Hits        41227    41224    -3     
+ Misses      15015    15012    -3     
+ Partials     3321     3319    -2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions

github-actions Bot commented Jun 2, 2026

Copy link
Copy Markdown

🚀 PR Preview Install Guide

🧰 CLI update

npm i -g https://pkg.pr.new/larksuite/cli/@larksuite/cli@6a540bab4179e68464c08f7e16672aa14a67f401

🧩 Skill update

npx skills add larksuite/cli#refactor/transport-single-owner -y -g

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
internal/transport/config.go (1)

4-11: 💤 Low value

Stale package doc comment.

The doc comment on line 4 still references proxyplugin but the package is now transport. Update for consistency.

📝 Proposed fix
-// Package proxyplugin implements the ~/.lark-cli/proxy_config.json based security proxy plugin mode.
+// Package transport implements the ~/.lark-cli/proxy_config.json based security proxy plugin mode.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/transport/config.go` around lines 4 - 11, Update the stale package
doc comment that still says "proxyplugin" so it matches the current package name
"transport": edit the top-of-file package comment (the block above the package
transport declaration) to replace "proxyplugin" with "transport" and ensure any
references in that comment (e.g., descriptions of behavior or filenames) remain
accurate and consistent with the transport package's responsibilities; keep the
rest of the comment content intact unless additional wording is needed for
correctness.
internal/cmdutil/transport.go (1)

176-186: 💤 Low value

Parameter transport now shadows the imported transport package.

With internal/transport newly imported (Line 12), the transport http.RoundTripper parameter shadows the package name inside wrapWithExtension. It compiles since the package isn't referenced here, but it's a readability/govet -shadow snag introduced by this PR. Consider renaming the parameter.

♻️ Proposed rename
-func wrapWithExtension(transport http.RoundTripper) http.RoundTripper {
+func wrapWithExtension(rt http.RoundTripper) http.RoundTripper {
 	p := exttransport.GetProvider()
 	if p == nil {
-		return transport
+		return rt
 	}
 	tr := p.ResolveInterceptor(context.Background())
 	if tr == nil {
-		return transport
+		return rt
 	}
-	return &extensionMiddleware{Base: transport, Ext: tr, ExtName: p.Name()}
+	return &extensionMiddleware{Base: rt, Ext: tr, ExtName: p.Name()}
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/cmdutil/transport.go` around lines 176 - 186, The parameter name
transport in wrapWithExtension shadows the imported transport package; rename
the parameter (e.g., baseTransport or rt) in the function signature and update
its usage inside wrapWithExtension and the returned extensionMiddleware
construction (referencing extensionMiddleware{Base: ..., Ext: tr, ExtName:
p.Name()}) so the package name is no longer shadowed and govet -shadow warnings
are resolved.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/cmdutil/factory_default.go`:
- Line 105: WarnIfProxied writes plain-text to the provided writer which can
emit warnings to f.IOStreams.ErrOut during credential resolution and break the
stderr JSON envelope; modify cachedHttpClientFunc and cachedLarkClientFunc to
avoid calling transport.WarnIfProxied with f.IOStreams.ErrOut during token
resolution path (DefaultTokenProvider.resolveUAT → p.httpClient()), instead gate
the warning emission behind the JSON envelope state or send warnings to a
non-JSON sink (e.g., an internal logger) so that WarnIfProxied is not invoked
with f.IOStreams.ErrOut during credential resolution; locate usages of
transport.WarnIfProxied, cachedHttpClientFunc, cachedLarkClientFunc and
DefaultTokenProvider.resolveUAT and change the callsite to either skip
WarnIfProxied or route its output away from f.IOStreams.ErrOut when credential
resolution is in progress.

In `@internal/transport/transport_test.go`:
- Around line 151-156: Update the stale doc comment header and references to
match the renamed test and current package: change the header name from
TestSharedTransport_InvalidConfigBlockerIsConcreteTransport to
TestPluginTransport_InvalidConfigBlockerIsConcreteTransport and replace the two
occurrences of util.Fallback with transport.Fallback so the comment accurately
documents the fail-closed invariant guarded by
TestPluginTransport_InvalidConfigBlockerIsConcreteTransport in this package.

---

Nitpick comments:
In `@internal/cmdutil/transport.go`:
- Around line 176-186: The parameter name transport in wrapWithExtension shadows
the imported transport package; rename the parameter (e.g., baseTransport or rt)
in the function signature and update its usage inside wrapWithExtension and the
returned extensionMiddleware construction (referencing extensionMiddleware{Base:
..., Ext: tr, ExtName: p.Name()}) so the package name is no longer shadowed and
govet -shadow warnings are resolved.

In `@internal/transport/config.go`:
- Around line 4-11: Update the stale package doc comment that still says
"proxyplugin" so it matches the current package name "transport": edit the
top-of-file package comment (the block above the package transport declaration)
to replace "proxyplugin" with "transport" and ensure any references in that
comment (e.g., descriptions of behavior or filenames) remain accurate and
consistent with the transport package's responsibilities; keep the rest of the
comment content intact unless additional wording is needed for correctness.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c492fb9a-8a79-4ee1-b092-03d268a3c2c4

📥 Commits

Reviewing files that changed from the base of the PR and between bc8e9bd and f6be704.

📒 Files selected for processing (19)
  • cmd/config/init_interactive.go
  • cmd/doctor/doctor.go
  • internal/auth/transport.go
  • internal/cmdutil/factory_default.go
  • internal/cmdutil/transport.go
  • internal/cmdutil/transport_test.go
  • internal/registry/remote.go
  • internal/transport/config.go
  • internal/transport/config_test.go
  • internal/transport/shared.go
  • internal/transport/shared_test.go
  • internal/transport/tls_ca.go
  • internal/transport/tls_ca_test.go
  • internal/transport/transport.go
  • internal/transport/transport_test.go
  • internal/transport/warn.go
  • internal/transport/warn_test.go
  • internal/update/update.go
  • internal/util/proxy.go
💤 Files with no reviewable changes (1)
  • internal/util/proxy.go

Comment thread internal/cmdutil/factory_default.go
Comment thread internal/transport/transport_test.go Outdated
…x util layering inversion

internal/util imported internal/proxyplugin (SharedTransport, FallbackTransport,
NewHTTPClient, and WarnIfProxied via proxyPluginStatus), so a foundational util
package depended up into a feature package, pulling binding/core/vfs into the
transitive cone of every util importer.

Move internal/proxyplugin -> internal/transport and make it the single owner of
outbound transport: fold the two SharedTransport functions into one Shared()
(proxy-plugin override -> LARK_CLI_NO_PROXY -> http.DefaultTransport), and move
Fallback/NewHTTPClient/WarnIfProxied/DetectProxyEnv/noProxyTransport out of the
now-deleted internal/util/proxy.go into the new package. The proxy-plugin probe
is demoted to a private pluginTransport(); the duplicate redactProxyURL collapses
to one. internal/util keeps no proxy code and is a leaf again.

Re-point all consumers (registry, doctor, config, auth, cmdutil, update) to
internal/transport. Behavior-preserving: package move + symbol rename + dedup.
Two new tests lock the fail-closed contract (plugin overrides NO_PROXY; malformed
config never falls through to direct egress).

Change-Id: I3e5b596e1a7f70e55995897140738a74ad4d6fd1
@liangshuo-1
liangshuo-1 force-pushed the refactor/transport-single-owner branch from f6be704 to 6a540ba Compare June 2, 2026 06:19
@liangshuo-1
liangshuo-1 merged commit 4710a29 into main Jun 2, 2026
20 of 21 checks passed
@liangshuo-1
liangshuo-1 deleted the refactor/transport-single-owner branch June 2, 2026 08:10
@liangshuo-1 liangshuo-1 mentioned this pull request Jun 2, 2026
1 task
liangshuo-1 added a commit that referenced this pull request Jun 2, 2026
Resolve internal/registry/remote.go import conflict by keeping BOTH sides:
the typed meta model (this branch) and the proxy-aware transport client
(main #1181/#1213). The changes are orthogonal — fetchRemoteMerged now uses
transport.NewHTTPClient(fetchTimeout) over the typed MergedRegistry. Only the
import block conflicted; the transport client line auto-merged.

Change-Id: Ia61ab32c39e5b4eadb05e7efe46ff0c8dcfce568
liangshuo-1 added a commit that referenced this pull request Jun 4, 2026
Resolve internal/registry/remote.go import conflict by keeping BOTH sides:
the typed meta model (this branch) and the proxy-aware transport client
(main #1181/#1213). The changes are orthogonal — fetchRemoteMerged now uses
transport.NewHTTPClient(fetchTimeout) over the typed MergedRegistry. Only the
import block conflicted; the transport client line auto-merged.
tuxedomm pushed a commit to zhumiaoxin/cli that referenced this pull request Jun 6, 2026
…x util layering inversion (larksuite#1213)

internal/util imported internal/proxyplugin (SharedTransport, FallbackTransport,
NewHTTPClient, and WarnIfProxied via proxyPluginStatus), so a foundational util
package depended up into a feature package, pulling binding/core/vfs into the
transitive cone of every util importer.

Move internal/proxyplugin -> internal/transport and make it the single owner of
outbound transport: fold the two SharedTransport functions into one Shared()
(proxy-plugin override -> LARK_CLI_NO_PROXY -> http.DefaultTransport), and move
Fallback/NewHTTPClient/WarnIfProxied/DetectProxyEnv/noProxyTransport out of the
now-deleted internal/util/proxy.go into the new package. The proxy-plugin probe
is demoted to a private pluginTransport(); the duplicate redactProxyURL collapses
to one. internal/util keeps no proxy code and is a leaf again.

Re-point all consumers (registry, doctor, config, auth, cmdutil, update) to
internal/transport. Behavior-preserving: package move + symbol rename + dedup.
Two new tests lock the fail-closed contract (plugin overrides NO_PROXY; malformed
config never falls through to direct egress).
This was referenced Jul 23, 2026
Closed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/XL Architecture-level or global-impact change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants